package com.imoblife.brainwavestus.service;

import java.io.File;

import com.imoblife.brainwavestus.BrainWavestusApplication;
import com.imoblife.brainwavestus.database.SQLiteManager;
import com.imoblife.brainwavestus.database.SQLiteManager.DownTaskTable;
import com.imoblife.brainwavestus.database.SycSqlite;
import com.imoblife.brainwavestus.model.Constant;
import com.imoblife.brainwavestus.newdownloadframe.DownLoadTaskInfo;
import com.imoblife.brainwavestus.oldDownloadFrame.DownLoadItem;
import com.imoblife.brainwavestus.oldDownloadFrame.DownLoadItemPragrame;
import com.imoblife.brainwavestus.oldDownloadFrame.RestoreTransactionsTask;
import com.imoblife.brainwavestus.oldDownloadFrame.DownLoadItem.CompleteListener;
import com.imoblife.brainwavestus.oldDownloadFrame.DownLoadItem.PrepareListener;
import com.imoblife.brainwavestus.product.Product;
import com.imoblife.brainwavestus.product.ProductInfo;
import com.imoblife.brainwavestus.product.Store;
import com.imoblife.brainwavestus.user.User;
import com.imoblife.brainwavestus.util.DBUtil;
import com.imoblife.brainwavestus.util.DebugUtil;
import com.imoblife.brainwavestus.util.MakePurchaseStateChenge;
import com.imoblife.brainwavestus.util.ProductUtil;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.util.Log;

public class DownloadService extends Service {

	private static final String TAG = "DownLoadSchedulerSystem";

	public static final int LEVEL_PREW = 1; // 预览文件的优先级

	public static final int LEVEL_DES = 2;// 描述文件优先级

	public static final int LEVEL_ICON = 2;// 产品图标的优先级

	public static final int LEVEL_MUSIC = 1;// 音频文件的优先级

	/* 预览开始下载命令 */
	public static final String COMMAND_RECAIVER_PREW_START = "command_receiver_prew_start";
	/* 预览结束下载命令 */
	public static final String COMMAND_RECAIVER_PREW_END = "command_receiver_prew_end";
	/* 音乐下载命令 */
	public static final String COMMAND_RECAIVER_MUSIC_DOWNLOAD = "command_receiver_music_download";
	/* 音乐重新下载命令 */
	public static final String COMMAND_RECAIVER_MUSIC_REDOWNLOAD = "command_receiver_music_redownload";
	/* 音乐取消下载命令 */
	public static final String COMMAND_RECAIVER_MUSIC_CANCEL = "command_receiver_music_cancel";
	/* 立即结束下载调度系统 */
	public static final String COMMAND_EXIT_DOWNLOAD_NOW = "command_exit_download_now";
	/* 等下载结束了 结束进程 */
	public static final String COMMAND_EXIT_DOWNLOAD_WAIT = "command_exit_download_wait";

	public static final String COMMAND_STOP_ALL_DOWNLOADING = "command_stop_all_downloading";

	public static final String COMMAND_START_ALL_DOWNLOADING = "command_start_all_downloading";

	/* 命令停止下载 */
	public static final String COMMAND_RECAIVER_STOP = "command_recaiver_stop";
	/* 命令开始下载 */
	public static final String COMMAND_RECAIVER_START = "command_recaiver_start";
	/* 回复账单的命令 */
	public static final String COMMAND_RESTORE_TRANSATION = "command_restore_transation";

	public static final String ACT_DOWNLOADINFO_FILTRE = "act_downloadinfo_filter";

	public static final String ACT_DOWNLOADINFO_EXTR = "act_download_extr";

	/* 下载任务命令意图 */
	public static final String ACT_SCHEDULER_DOWNLAOD = "ACT_SCHEDULER_DOWNLAOD";

	DownLoadItem runningDownLoadItem;// 正在执行下载的任务名

	BroadcastReceiver downloadCommandReceiver;/* 接受命令 */

	boolean isWaitExit = false;

	private static Thread currentThread;// 当前的线程
	
	private Context mCtx;
	private Store mStore;
	private DBUtil mDb;
	private User mUser;
	
	public static Handler updateUIHandler;

	public static void setUpdateUIHandler(Handler in) {
		updateUIHandler = in;
	}

	@Override
	public IBinder onBind(Intent intent) {
		
		return service;
	}
	
	public int getDownState(String taskName) {
		
		int intdownloadState = Constant.INT_DOWN_STATE_NOT_ENBLE;
		
		intdownloadState 
				= mDb.openForRead().getDownTaskState(taskName);
		mDb.closeDb();
		
		DebugUtil.debug(TAG, "strDownloadstate: " + intdownloadState);
			
		return intdownloadState;
	}
	
	public void startDownloadProduct(String taskName) {

		DebugUtil.debug(TAG, "schedulerDownLoadTask ,taskName:"
				+ taskName);

		int curentState = getDownState(taskName);

		if (curentState != DownLoadItemPragrame.DOWN_STATE_START) {

			setDownLoadInfoState(taskName,
					DownLoadItemPragrame.DOWN_STATE_START);
		}

		DownLoadItem downLoadItem = getSchedulerNextTask();

		DebugUtil.debug(TAG, "downloadItem" + downLoadItem.getTaskName());

		if (runningDownLoadItem == null || currentThread == null
				|| !currentThread.isAlive()) {

			runningDownLoadItem = downLoadItem;
			currentThread = getDownLoadThread();
			currentThread.start();

		} else if (downLoadItem.getLevel() >= runningDownLoadItem.getLevel()) {

			if (downLoadItem.getTaskName().equals(
					runningDownLoadItem.getTaskName())) {

				DebugUtil.debug(TAG, ">>" + runningDownLoadItem.getTaskName());

			} else {
				DownLoadItem tmp = runningDownLoadItem;
				runningDownLoadItem = downLoadItem;
				tmp.interrupt();
			}

		} else {

			DebugUtil.debug(TAG,
					" downLoadItem.getLevel()=" + downLoadItem.getLevel());
		}

	}

	public void cancelDownloadProduct(String taskName) throws RemoteException {
		
	}
	
	public void reDownloadProduct(String taskName) throws RemoteException {
		
		
	}
	
	public void exitDownloadProduct() throws RemoteException {
		
		
	}
	
	public void exitDownloadWaitProduct() throws RemoteException {
		
		
	}
	
	IDownloadService.Stub service = 
			new IDownloadService.Stub() {

				@Override
				public void startDonwload(String taskName)
						throws RemoteException {
						
					startDownloadProduct(taskName);
				}

				@Override
				public void cancel(String taskName) throws RemoteException {
						
					cancelDownloadProduct(taskName);
				}

				@Override
				public void reDownload(String taskName) throws RemoteException {
					
					reDownloadProduct(taskName);
				}

				@Override
				public void exitDownload() throws RemoteException {
					
					exitDownloadProduct();
				}

				@Override
				public void exitDownloadWait() throws RemoteException {
				
					exitDownloadWaitProduct();
				}
		
	};








	private DownLoadItem transform(String name) {


		String format = null;

		if (name.contains(".icon")) {
			format = "icon";
			name = name.replace(".icon", "");
		} else if (name.contains(".music")) {
			format = "music";
			name = name.replace(".music", "");

		} else if (name.contains(".des")) {
			format = "des";
			name = name.replace(".des", "");
		} else if (name.contains(".prew")) {
			format = "prew";
			name = name.replace(".prew", "");
		}

		DownLoadItem downLoadItem = new DownLoadItem(name, format);
		downLoadItem.setCompleteListener(new CompleteListener() {

			public void complete(String downloadname, int extr, long progress,
					long size) {
				
				if (extr == DownLoadItemPragrame.EXTR_SUCC) {
					
					DebugUtil.debug(TAG, "downname: " + downloadname
								+ "  download success~: "+ extr);
													
					setDownLoadInfoState(downloadname,
							DownLoadItemPragrame.DOWN_STATE_END);			

				} else if (extr != DownLoadItemPragrame.EXTR_INTERRUPT) {
					setDownLoadInfoState(downloadname,
							DownLoadItemPragrame.DOWN_STATE_FAILE);
				} else {

				}
				
				setDownloadInfoStateExtr(downloadname, extr);
			}
		});
		downLoadItem.setPrepareListener(new PrepareListener() {

			public void prepare(String downlaodname, int extr, long progress,
					long size) {

				if (getDownloadTaskState(downlaodname,
						DownloadService.this) == DownLoadItemPragrame.DOWN_STATE_CANCEL) {

					return;
				}

				if (extr == DownLoadItemPragrame.EXTR_SUCC) {

					setDownLoadInfoSize(downlaodname, size);
					setDownLoadInfoState(downlaodname,
							DownLoadItemPragrame.DOWN_STATE_START);
					
				} else {
					Log.d(TAG, "prepare  error>>" + downlaodname + "extr= "
							+ extr);
				}

			}
		});
		return downLoadItem;
	}

	public void setDownLoadInfoLevel(String name, int level) {
		
		mDb.openForWrite().updateDownInfo(name, 
							DBUtil.DOWN_TASK_LEVEL, 
							String.valueOf(level));
	}

	public void setDownLoadInfoSize(String name, long size) {
		
		mDb.openForWrite().updateDownInfo(name, 
							DBUtil.DOWN_FILE_SIZE, String.valueOf(size));
		mDb.closeDb();	
	}

	public void setDownLoadInfoState(String name, int state) {
		
		String productName = name.substring(0, name.indexOf(".")); 
		DebugUtil.debug(TAG, "tranform task name: " + productName);
		
		Product product = mStore.getProductByName(productName);
		ProductInfo pInfo = product.getProductInfo();
		
		pInfo.setDownloadState(ProductUtil.downloadStateTransform(state));
		pInfo.setChangeTime(ProductUtil.long2String(System.currentTimeMillis()));
		
		mDb.openForWrite().updateProduct(pInfo);
			
		mDb.updateDownInfo(name, 
				DBUtil.DOWN_TASK_STATE,
				String.valueOf(state));
		mDb.updateDownInfo(name, DBUtil.DOWN_TASK_CHANGE_TIME, 
				ProductUtil.long2String(
						System.currentTimeMillis()));
		mDb.closeDb();
	}

	public void setDownloadInfoStateExtr(String name, int stateExtr) {
		
		mDb.openForWrite().updateDownInfo(name, 
						DBUtil.DOWN_TASK_RSP_CODE,
						String.valueOf(stateExtr));
		mDb.closeDb();
	}

	Handler mStopHandler;

	@SuppressWarnings("deprecation")
	public void onStart(Intent intent, int startId) {
		DebugUtil.debug(TAG, "startId=" + startId);
		super.onStart(intent, startId);
		isWaitExit = false;

	}

	public void onCreate() {

		super.onCreate();
		
		BrainWavestusApplication app = 
				(BrainWavestusApplication)getApplication();
		mCtx = this;
		mStore = app.getStore();
		mUser = app.getUser();
		mDb = new DBUtil(this);
		
		antiSleep(this);
		registerCommandReceiver();
		mStopHandler = new Handler() {

			public void handleMessage(Message msg) {
				DebugUtil.debug(TAG, "oncreate");
				stopForeground(true);
				stopSelf();
				releaseantiSleep(DownloadService.this);
				unregisterCommandReceiver();
			}

		};		
			
	}

	/**
	 * ��ʼ�������
	 */
	public void begainSchedulerDownLoad() {
		if (currentThread == null || !currentThread.isAlive()) {
			runningDownLoadItem = getSchedulerNextTask();
			if (runningDownLoadItem != null) {
				currentThread = getDownLoadThread();
				currentThread.start();
			}
		}

	}

	int mStartId;

	PowerManager.WakeLock mWakeLock;

	/**
	 * ��˯��
	 * 
	 * @param context
	 */
	void antiSleep(Context context) {
		try {
			PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
			mWakeLock = pm
					.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "XYTEST");
			mWakeLock.acquire();

		} catch (Exception e) {

		}
	};

	/**
	 * ����˯��
	 * 
	 * @param context
	 */
	void releaseantiSleep(Context context) {
		try {
			mWakeLock.release();
		} catch (Exception e) {

		}
	}

	/**
	 * ע��㲥
	 */
	void registerCommandReceiver() {
		downloadCommandReceiver = new BroadcastReceiver() {

			@SuppressWarnings("deprecation")
			public void onReceive(Context context, Intent intent) {

				DebugUtil.debug(TAG, intent.getAction());

				try {

					if (intent.getAction().equals(ACT_SCHEDULER_DOWNLAOD)) {

						String command = intent.getStringExtra("command");
						String commandText = intent.getStringExtra(command);

						DebugUtil.debug(TAG, "�յ�����--" + command + "��������"
								+ commandText);

						if (command.equals(COMMAND_RECAIVER_PREW_START)) {

							schedulerPrewTask(commandText);

						} else if (command.equals(COMMAND_RESTORE_TRANSATION)) {

							restoreTransations();

						} else if (command
								.equals(COMMAND_RECAIVER_MUSIC_DOWNLOAD)) {

							schedulerMusicTask(commandText);

						} else if (command
								.equals(COMMAND_RECAIVER_MUSIC_REDOWNLOAD)) {

							schedulerMusicRedownLoadTask(commandText);

						} else if (command
								.equals(COMMAND_RECAIVER_MUSIC_CANCEL)) {

							cancelDownLoadTask(commandText);

						} else if (command
								.equals(COMMAND_START_ALL_DOWNLOADING)) {

							begainSchedulerDownLoad();

						} else if (command.equals(COMMAND_STOP_ALL_DOWNLOADING)) {

							stopDownloading();

						} else if (command.equals(COMMAND_EXIT_DOWNLOAD_WAIT)) {

							isWaitExit = true;
							if (currentThread == null
									|| !currentThread.isAlive()) {

								runningDownLoadItem = getSchedulerNextTask();
								if (runningDownLoadItem != null) {
									currentThread = getDownLoadThread();
									currentThread.start();
								}

							}

						} else if (command.equals(COMMAND_EXIT_DOWNLOAD_NOW)) {

							while (true) {
								if (currentThread.isAlive()) {
									runningDownLoadItem.interrupt();
									runningDownLoadItem = null;

								} else {

									mStopHandler.sendEmptyMessage(0);

									return;
								}
								Thread.sleep(1000);
							}

						}

					} else if (intent.getAction().equals(
							ConnectivityManager.CONNECTIVITY_ACTION)) {

						NetworkInfo networkInfo = intent
								.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);

						DebugUtil.debug(TAG, "�յ�����仯=" + networkInfo.isConnected());

						if (networkInfo.isConnected()) {
							begainSchedulerDownLoad();
						}
					}

				} catch (Exception e) {

					DebugUtil.debug(TAG, "onReceive �׳��쳣");
				}

			}
		};

		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(ACT_SCHEDULER_DOWNLAOD);
		intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(downloadCommandReceiver, intentFilter);

	}

	void unregisterCommandReceiver() {
		unregisterReceiver(downloadCommandReceiver);
	}

	/**
	 * ��ȡ���ص��߳�
	 * 
	 * @return
	 */
	Thread getDownLoadThread() {

		return new Thread("downloadThread") {

			public void run() {
				SharedPreferences preferences = getSharedPreferences(
						"downloadThread", 0);

				preferences.edit().putBoolean("isDowning", true).commit();
				DownLoadItem tmp = runningDownLoadItem;

				if (tmp == null
						|| (currentThread != null
						&& currentThread != this)){

					if (isWaitExit) {
						DebugUtil.debug(TAG, "������");
						sendBroadcast(new Intent(COMMAND_EXIT_DOWNLOAD_NOW));
					}

					preferences.edit().putBoolean("isDowning", false).commit();
					return;
				}

				try {
					tmp.run();
				} catch (Exception e) {

				}

				if (tmp.isInterrupted()){

					if (runningDownLoadItem == null) {
						DebugUtil.debug(TAG, "���" + tmp.getTaskName() + ">> ���ؽ���");
					} else {
						DebugUtil.debug(TAG,
								"���" + tmp.getTaskName() + ">> ��һ����������>>"
										+ runningDownLoadItem.getTaskName());
					}

				} else {

					runningDownLoadItem = getSchedulerNextTask();
	
					if (runningDownLoadItem == null
							|| tmp.getDataName().equals(
									runningDownLoadItem.getDataName())) {

						runningDownLoadItem = null;

					}

				}
				run();
			}

		};
	};

	/**
	 * ���Ԥ����������
	 * 
	 * @param name
	 */
	private void schedulerPrewTask(String name) {
		schedulerDownLoadTask(name);
	}

	/**
	 * ���һ����������
	 * 
	 * @param downLoadTaskName
	 */
	protected void schedulerDownLoadTask(final String downLoadTaskName) {
		
		
		DebugUtil.debug(TAG, "schedulerDownLoadTask ,taskName:" 
								+ downLoadTaskName);
		
		int curentState = MakePurchaseStateChenge.getTaskState(
				downLoadTaskName, this);

		if (curentState != DownLoadItemPragrame.DOWN_STATE_START) {

			setDownLoadInfoState(downLoadTaskName,
					DownLoadItemPragrame.DOWN_STATE_START);
		}

		DownLoadItem downLoadItem = getSchedulerNextTask();

		DebugUtil.debug(TAG, "downloadItem" + downLoadItem.getTaskName());

		if (runningDownLoadItem == null || currentThread == null
				|| !currentThread.isAlive()) {

			runningDownLoadItem = downLoadItem;
			currentThread = getDownLoadThread();
			currentThread.start();

		} else if (downLoadItem.getLevel() >= runningDownLoadItem.getLevel()) {

			if (downLoadItem.getTaskName().equals(
					runningDownLoadItem.getTaskName())) {

				DebugUtil.debug(TAG,
						">>" + runningDownLoadItem.getTaskName());

			} else {
				DownLoadItem tmp = runningDownLoadItem;
				runningDownLoadItem = downLoadItem;
				tmp.interrupt();
			}

		} else {

			DebugUtil.debug(TAG,
					" downLoadItem.getLevel()=" + downLoadItem.getLevel());
		}

	}

	/**
	 * 
	 * 
	 * @param taskName
	 */
	private void schedulerMusicTask(String taskName) {
		schedulerDownLoadTask(taskName);
	}

	/**
	 * ���һ����Ƶ������
	 * 
	 * @param taskName
	 */
	private void schedulerMusicRedownLoadTask(String taskName) {

		redownloadTask(taskName);
		if (runningDownLoadItem != null
				&& runningDownLoadItem.getDataName().equals(taskName)) {
			runningDownLoadItem.interrupt();
			runningDownLoadItem = null;
			DebugUtil.debug(TAG, "schedulerMusicRedownLoadTask>> task Name="
					+ taskName);
		}

		schedulerMusicTask(taskName);
	}

	public static float getProgressDownload(String taskName, Context context) {

		String subPath = taskName.substring(taskName.indexOf(".") + 1);
		subPath += "/" + taskName;
		File file = new File(DownLoadItem.rootPath + subPath);
		int length = 0;
		if (file.exists()) {
			length = (int) file.length();
		}

		DBUtil db = new DBUtil(context);
		
		int size = db.openForRead().getDownFileSize(taskName);
		db.closeDb();
		
		if (length != 0 && size != 0) {
			float progress = (length * 1.0f / size) * 100;
			return progress;
		}

		return 0;
	};

	private void cancelDownLoadTask(String taskName) {

		if (getDownloadTaskState(taskName, this) == DownLoadItemPragrame.DOWN_STATE_END) {
			return;
		}

		setDownLoadInfoState(taskName, DownLoadItemPragrame.DOWN_STATE_CANCEL);


		if (runningDownLoadItem != null
				&& runningDownLoadItem.getTaskName().equals(taskName)) {
			runningDownLoadItem.interrupt();
			runningDownLoadItem = getSchedulerNextTask();
		}
	}

	private void redownloadTask(String taskName) {

		transform(taskName).setRedowmLoad();
		setDownLoadInfoState(taskName, DownLoadItemPragrame.DOWN_STATE_START);
		setDownLoadInfoSize(taskName, 0);
	}

	private DownLoadItem getSchedulerNextTask() {

		DownLoadItem downLoadItem = getNextDownloadNormalTask();

		if (downLoadItem != null) {
			return downLoadItem;
		}

		return getNextDownloadExceptionTask();

	}


	private DownLoadItem getNextDownloadNormalTask() {


		String taskName = mDb.openForRead().getHighestLevelDownTask();
		mDb.closeDb();
		
		DownLoadItem downLoadItem = null;
		
		if (taskName != null) {
			
			downLoadItem = transform(taskName);
		}

		return downLoadItem;
	}

	private DownLoadItem getNextDownloadExceptionTask() {

		DebugUtil.debug(TAG, "get highest fail task");

		String failDownName = mDb.openForRead().getHighestFailedTask();
		
		DownLoadItem downLoadItem = null;
		
		if(failDownName != null) {
			
			downLoadItem = transform(failDownName);			
		}

		return downLoadItem;
	}

	public void stopDownloading() {
		if (currentThread != null && currentThread.isAlive()) {
			if (runningDownLoadItem != null) {
				runningDownLoadItem.interrupt();
				runningDownLoadItem = null;
			}
		}
	}

	public static boolean isDownloading() {
		if (currentThread != null && currentThread.isAlive()) {
			return true;
		}
		return false;
	}


	public void restoreTransations() {

		if (currentThread == null || !currentThread.isAlive()
				|| runningDownLoadItem == null) {
			runningDownLoadItem = new RestoreTransactionsTask(this);
			currentThread = getDownLoadThread();
			currentThread.start();
		} else {
			DownLoadItem tmp = runningDownLoadItem;
			runningDownLoadItem = new RestoreTransactionsTask(this);
			tmp.interrupt();
		}

	}

	public int onStartCommand(Intent intent, int flags, int startId) {

		return START_NOT_STICKY;
	}


	public static int getDownloadTaskState(String taskName, Context context) {
		
		
		DebugUtil.debug(TAG, "getTaskState=" + taskName);
		
		DBUtil db = new DBUtil(context);
		
		int downState = db.openForRead().getDownTaskState(taskName);
		db.closeDb();
		
		return downState;
	}

	public void onDestroy() {
		DebugUtil.debug(TAG, "onDestroy");
	}
}
